/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { RuleEngine } from "./node-rules.js";

function register_TEST_01() {
  // 定义一个规则对象数组
  let rules = [
    {
      condition: (R, f) => {
        R.when(f.card == "VISA");
      },
      consequence: (R, f) => {
        R.stop();
        f.result = "Custom Result";
      },
      priority: 4
    },
    {
      condition: (R, f) => {
        R.when(f.transactionTotal < 1000);
      },
      consequence: (R, f) => {
        R.next();
      },
      priority: 8
    }
  ];
  let R1 = new RuleEngine();

  let startTime = Date.now()
  for (let i = 0; i < 1000; i++) {
    R1.register(rules[0]);
  }
  let endTime = Date.now()

  if(R1.rules[0] == undefined){
    throw new Error('Drools_register(object) Error')
  }
  print(`Drools_register: ${endTime - startTime} ms`)
}

async function execute_TEST_01() {
  let rule = {
    name: "sample rule name",
    id: "xyzzy",
    condition: (R, f) => {
      R.when(f.input === true);
    },
    consequence: (R, f) => {
      f.result = true;
      f.ruleName = R.rule().name;
      f.ruleID = R.rule().id;
      R.stop();
    }
  };
  let R3 = new RuleEngine(rule);
  let promises = [];

  let totalTime = 0;
  promises.push(new Promise((resolve, reject) => {
    let startTime = Date.now();
    R3.execute({input: true,}, (results) => {
      let endTime = Date.now();
      totalTime += endTime - startTime;
      resolve(results);
    }); 
  }));

  Promise.all(promises).then((results) => {
    if(results[0].ruleName !== 'sample rule name'){
      throw new Error('Drools_register(object) Error')
    }
    print(`Drools_execute: ${totalTime} ms`)
  });
}

async function execute_TEST_02() {
  let rule = {
    name: "sample rule name",
    id: "xyzzy",
    condition: (R, f) => {
      R.when(f.input === true);
    },
    consequence: (R, f) => {
      f.result = true;
      f.ruleName = R.rule().name;
      f.ruleID = R.rule().id;
      R.stop();
    }
  };
  let startTime = 0;
  let R3 = new RuleEngine(rule);  
  let myPromise = new Promise((resolve, reject) => {
      startTime = Date.now();
      R3.execute({input: true,}, (results) => {
        resolve(results);
      }); 
  })
  myPromise.then((results) => {
    print(`Drools_execute: ${Date.now() - startTime} ms`)
  });
  
  await myPromise;
}

function when_TEST() {
  let time = 0;
  let printTime = (isEnd) => {
    if (isEnd) {
      print(`Drools_when: ${Date.now() - time} ms`)
    } else {
      time = Date.now();
    }
  }

  let rules = {
    condition: (R,f) => {
      printTime(false);
      for (let i = 0; i < 100000; i++) {
        R.when(f.transactionTotal < 1000);
      }
      printTime(true);
    },
    consequence: (R,f) => {
      f.result = "Custom Result when";
      R.stop();
    }
  };

  let R5 = new RuleEngine(rules);
  R5.execute({transactionTotal: 400}, (results) => {
    if(results.result !== 'Custom Result when'){
      throw new Error('Drools_registerwhen Error')
    }
  });
}

function next_TEST() {
  let time = 0;
  let printTime = (isEnd) => {
    if (isEnd) {
      print(`Drools_next: ${Date.now() - time} ms`)
    } else {
      time = Date.now();
    }
  }

  let rules = [
    {
      condition: (R,f) => {
        R.when(f.transactionTotal < 1000);
      },
      consequence: (R,f) => {
        printTime(false);
        for (let i = 0; i < 10000; i++) {
          R.next();
        }
        printTime(true);
        f.result = "Custom Result next";
      },
      priority: 8
    },
    {
      condition: (R, f) => {
        R.when(f.card == "VISA");
      },
      consequence: (R, f) => {
        R.stop();
      },
      priority: 4
    },
  ];

  let R6 = new RuleEngine(rules);
  R6.execute({transactionTotal: 200, card: "VISA"}, (results) => {
    if(results.result !== 'Custom Result next'){
      throw new Error('Drools_next Error')
    }
  });
}

function stop_TEST() {
  let time = 0;
  let printTime = (isEnd) => {
    if (isEnd) {
      print(`Drools_stop: ${Date.now() - time} ms`)
    } else {
      time = Date.now();
    }
  }

  let rules = {
    condition: (R,f) => {
      R.when(f.transactionTotal < 1000);
    },
    consequence: (R,f) => {
      printTime(false);
      for (let i = 0; i < 10000; i++) {
        R.stop();
      }
      printTime(true);
      f.result = "Custom Result stop";
    }
  }

  let R7 = new RuleEngine(rules);
  R7.execute({transactionTotal: 200}, (results) => {
    if(results.result !== 'Custom Result stop'){
      throw new Error('Drools_stop Error')
    }
  });
}

function restart_TEST() {
  let time = 0;
  let printTime = (isEnd) => {
    if (isEnd) {
      print(`Drools_restart: ${Date.now() - time} ms`)
    } else {
      time = Date.now();
    }
  }

  let rules = {
    condition: (R,f) => {
      R.when(f.transactionTotal < 1000);
    },
    consequence: (R,f) => {
      f.transactionTotal = 2000
      printTime(false);
      for (let i = 0; i < 100000; i++) {
        R.restart();
      }
      printTime(true);
      f.result = "Custom Result restart";
    }
  }

  let R8 = new RuleEngine(rules);
  R8.execute({transactionTotal: 200}, (results) => {
    if(results.result !== 'Custom Result restart'){
      throw new Error('Drools_restart Error')
    }
  });
 
}

async function Switch() {
    register_TEST_01()
    when_TEST()
    next_TEST()
    stop_TEST()
    restart_TEST()
    // await execute_TEST_01()
    await execute_TEST_02()
    
}
for(let i = 0; i < 1; i ++) {
  await Switch()
}

